package cn.tedu.knows.sys.interceptor;

import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

// 别忘了写@Component
@Component
public class AuthInterceptor implements HandlerInterceptor {

    @Resource
    private RestTemplate restTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获得请求中包含的jwt
        String token=request.getParameter("accessToken");
        // 利用auth授权服务器功能解析token令牌
        // 获得令牌中包含的用户信息
        String url=
         "http://auth-service/oauth/check_token?token={1}";
        Map<String,Object> map=restTemplate.getForObject(
                        url,Map.class,token);
        // Map会自动解析json格式中的各种信息
        // 而我们只需要user_name和authorities
        // 接收用户名
        String username=map.get("user_name").toString();
        // 接收所有auth,使用List<String>来接收
        List<String> list=(List<String>)map
                                    .get("authorities");
        // 获得用户必要信息,保存到Spring-Security中
        // 因为保存到Spring-Security是框架提供的功能,
        // 所以方式是固定的
        String[] auth=list.toArray(new String[0]);
        UserDetails userDetails= User.builder()
                .username(username)
                .password("")
                .authorities(auth)
                .build();
        // 我们已经获得了用户详情对象
        // 下面要讲它保存在Spring-Security框架中
        // 以便在其他控制器中获取
        // Spring-Security给定了固定的方式来实现这个功能
        PreAuthenticatedAuthenticationToken
                authenticationToken=
                new PreAuthenticatedAuthenticationToken(
                        userDetails,
                        userDetails.getPassword(),
                        AuthorityUtils.createAuthorityList(auth)
                );
        //设置关联当前请求才能保存到Spring-Security
        authenticationToken.setDetails(
                new WebAuthenticationDetails(request)
        );
        // 将当前用户信息保存到Spring-Security上下文对象
        // 上下文对象就是指保存用户信息的容器
        SecurityContextHolder.getContext()
                .setAuthentication(authenticationToken);
        // 最后一定要返回true
        return true;
    }
}







